package com.jy.appmarket.cards;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.jy.appmarket.R;
import com.jy.appmarket.activity.AppDetailActivity;
import com.jy.appmarket.activity.AppUpdateActivity.AppUpdateModelWithDownload;
import com.jy.appmarket.database.AppUpdateDatabase;
import com.jy.appmarket.dialog.TextAndCheckBoxDialog;
import com.jy.appmarket.download.DownloadActivity;
import com.jy.appmarket.download.DownloadItem;
import com.jy.appmarket.download.DownloadService;
import com.jy.appmarket.download.DownloadUtils;
import com.jy.appmarket.model.AppUpdateModel;
import com.jy.appmarket.statistics.ApkSource;
import com.jy.appmarket.utils.AsyncImageLoader;
import com.jy.appmarket.utils.Prefs;
import com.jy.appmarket.utils.UITools;
import com.ms.square.android.expandabletextview.ExpandableTextView;
import com.ms.square.android.expandabletextview.ExpandableTextView.OnExpandStateChangeListener;

public class AppUpdateUICard extends DownloadableUICard {

	private static String TAG = "AppUpdateCard";

	private AppUpdateModelWithDownload mAppUpdateData;

	private int mBlueTextColor;
	private int mOrangeTextColor;
	private int mGrayTextColor;

	private boolean mIsExpandable = false;

	private TextView mVersion = null;
	private TextView mSize = null;
	private View mDownloadLayout = null;
	private Button mActionBtn = null;

	private TextView mProgressStatus = null;
	private TextView mProgressSize = null;
	private ProgressBar mProgress = null;
	private ImageButton mIgnoreBtn = null;

	private long mDowloadSpeed = 0;
	private long mDownloadedSize = 0;

	private TextAndCheckBoxDialog mTipDialog = null;
	AppUpdateUICardCallBack mListener;

	public interface AppUpdateUICardCallBack {
		void onNeedToReloadData(AppUpdateModelWithDownload data);

		void onNeedToInstallApp(String downloadId);

		void onNeedToStartDownload(String downloadId);

		void onNeedToStopDownload(String downloadId);

		void onNeedToAddNewDownload(AppUpdateModel m);

		void onNeedToCorrectOutOfDateDownload(AppUpdateModel m);
	}

	public AppUpdateUICard(Context context, AppUpdateModelWithDownload data,
			AppUpdateUICardCallBack l) {
		super(context, R.layout.app_update_item_layout);
		if (data == null) {
			return;
		}
		mListener = l;
		mAppUpdateData = data;
		init();
	}

	public AppUpdateModel getAppUpdateModel() {
		if (mAppUpdateData == null) {
			return null;
		}

		return mAppUpdateData.aum;
	}

	private void init() {
		Resources r = getContext().getResources();
		mBlueTextColor = r.getColor(R.color.download_btn_blue_style_text);
		mOrangeTextColor = r.getColor(R.color.download_btn_orange_style_text);
		mGrayTextColor = r.getColor(R.color.download_btn_gray_style_text);
	}

	private String formatDuring(long begin, long end) {
		long mss = end - begin;

		long days = mss / (1000 * 60 * 60 * 24);
		if (days == 1) {
			return "1天前";
		} else if (days > 1) {
			Date d = new Date(begin);
			SimpleDateFormat sdf = new SimpleDateFormat("MM月dd日");
			return sdf.format(d);
		}

		long hours = (mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
		if (hours >= 1) {
			return hours + "小时前";
		}

		return "刚刚";
	}

	private String getUpdateDateString() {
		StringBuilder sb = new StringBuilder();
		sb.append("\n\n");
		sb.append(formatDuring(mAppUpdateData.aum.getLastModified(), System.currentTimeMillis()));
		sb.append("更新");
		return sb.toString();
	}

	private String getChangeLog(boolean isExpanded) {
		StringBuilder sb = new StringBuilder();
		sb.append(getContext().getString(R.string.new_version_feature));

		String changelog = mAppUpdateData.aum.getChangeLog();
		if (TextUtils.isEmpty(changelog)) {
			sb.append(getContext().getString(R.string.not_available));
			sb.append(getUpdateDateString());
			return sb.toString();
		}

		if (isExpanded) {
			String expandlog = changelog.replaceAll("\r", "");
			expandlog = expandlog.replaceAll("<br />|<br/>", "\n");
			sb.append("\n");

			// 最后是一个换行,则去掉最后一个换行，因为getUpdateDateString函数中会增加两个换行。
			if (expandlog.lastIndexOf("\n") == expandlog.length() - 1 && expandlog.length() >= 2) {
				expandlog = expandlog.substring(0, expandlog.length() - 1);
			}

			sb.append(expandlog);
			sb.append(getUpdateDateString());
			return sb.toString();
		}

		String expandlog = changelog.replaceAll("\r", "");
		expandlog = expandlog.replaceAll("<br />|<br/>", "");
		expandlog = expandlog.replaceAll("\n", "");
		sb.append(expandlog);
		sb.append(getUpdateDateString());

		return sb.toString();
	}
	
	private Spanned getVersionString(){
		StringBuilder sb = new StringBuilder();

		String installVersionString = "";
		PackageManager manager = getContext().getPackageManager();
		try {
			PackageInfo info = manager.getPackageInfo(mAppUpdateData.aum.getPackageName(), 0);
			installVersionString = info.versionName;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}

		sb.append("版本：");
		sb.append(installVersionString);
		sb.append(" -> ");
		sb.append("<font color=\"#00adff\">");
		sb.append(mAppUpdateData.aum.getVersionName());
		sb.append("</font>");
		
		return Html.fromHtml(sb.toString());
	}
	
	private Spanned getSizeString(boolean isZero){
		StringBuilder sb = new StringBuilder();
		String size = UITools.normalizationFileSize(mAppUpdateData.aum.getSize());
		if (!isZero) {
			sb.append("大小：");
			sb.append(size);
		} else {
			sb.append("<font color=\"#00adff\">");
			sb.append(getContext().getString(R.string.wait_for_install));
			sb.append("</font>");
		}
		
		return Html.fromHtml(sb.toString());
	}

	
	private static boolean sIsExpanding = false;
	
	@Override
	public void setupInnerViewElements(ViewGroup parent, View view) {
		if (mAppUpdateData == null) {
			return;
		}

		View appInfoLayout = parent.findViewById(R.id.app_update_info_layout);
		final TextView version = parent.findViewById(R.id.app_update_verson);
		version.setSelected(true);
		appInfoLayout.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				//Log.e(TAG, "vc in update:" + mAppUpdateData.aum.getVersionCode());
				
				Intent detail = new Intent(getContext(), AppDetailActivity.class);
				detail.putExtra(AppDetailActivity.EXTRA_NAME, mAppUpdateData.aum.getTitle());
				detail.putExtra(AppDetailActivity.EXTRA_PKG, mAppUpdateData.aum.getPackageName());
				detail.putExtra(AppDetailActivity.EXTRA_SOURCE,
						ApkSource.toSourceString(getApkSource()));
				getContext().startActivity(detail);
			}
		});

		TextView appName = parent.findViewById(R.id.app_update_app_name);
		appName.setText(mAppUpdateData.aum.getTitle());

		ImageView appIcon = parent.findViewById(R.id.app_update_app_icon);
		AsyncImageLoader.getInstance(mContext).displayImage(mAppUpdateData.aum.getIconPath(),
				appIcon, R.drawable.default_loading_icon, false);

		if(!sIsExpanding){
			final ExpandableTextView etv = parent
					.findViewById(R.id.app_update_expand_text_view);
			String changeLog = getChangeLog(mIsExpandable);
			etv.setText(changeLog, !mIsExpandable);
			etv.setOnExpandStateChangeListener(new OnExpandStateChangeListener() {
				@Override
				public void onExpandStateStartChange(TextView textView, boolean isExpanded) {
					
					sIsExpanding = true;
					
					if (!mIsExpandable) {
						String changeLog = getChangeLog(true);
						etv.setText(changeLog);
					}
				}

				@Override
				public void onExpandStateChanged(TextView textView, boolean isExpanded) {
					mIsExpandable = isExpanded;
					if (!mIsExpandable) {
						String changeLog = getChangeLog(false);
						etv.setText(changeLog, !mIsExpandable);
					}
					
					sIsExpanding = false;
				}
			});
		}
		
		mVersion = parent.findViewById(R.id.app_update_verson);
		mSize = parent.findViewById(R.id.app_update_size);
		mDownloadLayout = parent.findViewById(R.id.app_update_dl_layout);
		mActionBtn = parent.findViewById(R.id.app_update_button);
		mProgressStatus = parent.findViewById(R.id.app_update_dl_status);
		mProgressSize = parent.findViewById(R.id.app_update_dl_schedule);
		mProgress = parent.findViewById(R.id.app_update_dl_progressbar);
		mIgnoreBtn = parent.findViewById(R.id.ignore_btn);

		mActionBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (mAppUpdateData.aum.isIgnore()) {
					AppUpdateDatabase db = AppUpdateDatabase.getInstance(getContext());
					db.setIgnore(mAppUpdateData.aum.getPackageName(), false);

					if (mListener != null) {
						mListener.onNeedToReloadData(mAppUpdateData);
					}
				} else {
					doActionButtonClicked();
				}

			}
		});

		mIgnoreBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (!Prefs.getAppUpdateIgnoreDialogFlag(getContext())) {
					showIgnoreDialog();
				} else {
					AppUpdateDatabase db = AppUpdateDatabase.getInstance(getContext());
					db.setIgnore(mAppUpdateData.aum.getPackageName(), true);

					if (mListener != null) {
						mListener.onNeedToReloadData(mAppUpdateData);
					}
				}
			}
		});

		if (mAppUpdateData.aum.isIgnore()) {
			setupViewWhendIgnored();
		} else {
			setupViewByStatus();
		}
	}

	private void doActionButtonClicked() {
		String dlId = DownloadUtils.generateDownloadId(mAppUpdateData.aum.getPackageName(),
				mAppUpdateData.aum.getVersionCode());
		int status = ((DownloadActivity) getContext()).getDownloadStatus(dlId,
				mAppUpdateData.aum.getPackageName(), mAppUpdateData.aum.getVersionCode());

		switch (status) {
		case DownloadService.STATUS_INSTALLED:
			try {
				Intent intent = getContext().getPackageManager().getLaunchIntentForPackage(
						mAppUpdateData.aum.getPackageName());
				getContext().startActivity(intent);
			} catch (Exception e) {
				e.printStackTrace();
				Toast.makeText(getContext(), "打开失败", Toast.LENGTH_SHORT).show();
			}
			break;
		case DownloadService.STATUS_CAN_INSTALL:
			if (mListener != null) {
				mListener.onNeedToInstallApp(dlId);
			}
			break;

		case DownloadService.STATUS_PAUSED_BY_ERROR:
		case DownloadService.STATUS_PAUSED_BY_USER:
			if (mListener != null) {
				mListener.onNeedToStartDownload(dlId);
			}
			break;

		case DownloadService.STATUS_DOWNLOADING:
		case DownloadService.STATUS_PENDING:
			if (mListener != null) {
				mListener.onNeedToStopDownload(dlId);
			}
			break;
		case DownloadService.STATUS_DOWNLOAD_OUT_OF_DATE: // 下载过期状态，强制处理为有更新状态，点击后重新开始下载
			if (mListener != null) {
				mListener.onNeedToCorrectOutOfDateDownload(mAppUpdateData.aum);
			}

			break;
		case DownloadService.STATUS_NEED_TO_UPDATE:
			if (mListener != null) {
				mListener.onNeedToAddNewDownload(mAppUpdateData.aum);
			}
			break;

		case DownloadService.STATUS_PREPARE_TO_DOWNLOAD:
		case DownloadService.STATUS_PREPARE_TO_STOP:
		case DownloadService.STATUS_INSTALLING:
			// do nothing
			break;
		case DownloadService.STATUS_PAUSED_BY_MOBILE_NETWORK:
		case DownloadService.STATUS_NO_STATUS:
			Log.e(TAG, "wrong status happen:" + status);
			break;

		default:
			break;
		}

	}

	private void showIgnoreDialog() {
		if (mTipDialog == null) {
			mTipDialog = new TextAndCheckBoxDialog(getContext());
			mTipDialog.showTitle(R.string.ignore_update);
			mTipDialog.setContent(R.string.ignore_tips);
			mTipDialog.setButtonLeftText(R.string.cancel);
			mTipDialog.setButtonRightText(R.string.confirm);
			mTipDialog.setLeftButtonOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					mTipDialog.cancel();
				}
			});

			mTipDialog.setRightButtonOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					mTipDialog.cancel();

					if (mTipDialog.getCheckBoxState()) {
						Prefs.saveAppUpdateIgnoreDialogFlag(getContext(), true);
					}

					AppUpdateDatabase db = AppUpdateDatabase.getInstance(getContext());
					db.setIgnore(mAppUpdateData.aum.getPackageName(), true);

					if (mListener != null) {
						mListener.onNeedToReloadData(mAppUpdateData);
					}
				}
			});
		}

		if (mTipDialog.isShowing()) {
			return;
		}

		mTipDialog.show();
	}

	private void setupViewWhendIgnored() {
		mDownloadLayout.setVisibility(View.GONE);
		mVersion.setVisibility(View.VISIBLE);
		mSize.setVisibility(View.VISIBLE);

		mVersion.setText(getVersionString());
		mSize.setText(getSizeString(false));
		
		setActionButton(mGrayTextColor, R.drawable.download_button_gray, getContext()
				.getResources().getString(R.string.cancel_ignore), true);

		mIgnoreBtn.setVisibility(View.GONE);
	}

	private void setActionButton(int textColor, int bgDrawableId, String text, boolean clickable) {
		mActionBtn.setTextColor(textColor);
		mActionBtn.setBackgroundResource(bgDrawableId);
		mActionBtn.setText(text);
		mActionBtn.setClickable(clickable);
	}

	private void setDownloadProgressLayoutItem(String statusText, String sizeText, int progress) {
		mProgressStatus.setText(statusText);
		mProgressSize.setText(sizeText);

		if (progress < 0) {
			mProgress.setIndeterminate(true);
		} else {
			mProgress.setIndeterminate(false);
			mProgress.setProgress(progress);
		}
	}

	private void setupViewByStatus() {
		String dlId = DownloadUtils.generateDownloadId(mAppUpdateData.aum.getPackageName(),
				mAppUpdateData.aum.getVersionCode());
		int status = ((DownloadActivity) getContext()).getDownloadStatus(dlId,
				mAppUpdateData.aum.getPackageName(), mAppUpdateData.aum.getVersionCode());

		if (mIgnoreBtn == null) {// 因为没有正常数据造成的bug，临时解决
			return;
		}

		mIgnoreBtn.setVisibility(View.VISIBLE);
		
		switch (status) {

		case DownloadService.STATUS_INSTALLED:
			mDownloadLayout.setVisibility(View.GONE);
			mVersion.setVisibility(View.VISIBLE);
			mSize.setVisibility(View.VISIBLE);
			
			mVersion.setText(getVersionString());
			mSize.setText(getSizeString(false));
			setActionButton(mGrayTextColor, R.drawable.download_button_gray, getContext()
					.getResources().getString(R.string.open), true);
			break;

		case DownloadService.STATUS_INSTALLING:
			
			mDownloadLayout.setVisibility(View.VISIBLE);
			mVersion.setVisibility(View.GONE);
			mSize.setVisibility(View.GONE);
			
			setActionButton(mGrayTextColor, R.drawable.download_button_gray, getContext()
					.getResources().getString(R.string.installing), false);
			setDownloadProgressLayoutItem(getContext().getResources()
					.getString(R.string.installing), "", -1);

			break;
		case DownloadService.STATUS_CAN_INSTALL:
			mDownloadLayout.setVisibility(View.GONE);
			mVersion.setVisibility(View.VISIBLE);
			mSize.setVisibility(View.VISIBLE);
			
			mVersion.setText(getVersionString());
			mSize.setText(getSizeString(true));
			
			setActionButton(mBlueTextColor, R.drawable.download_button_blue, getContext()
					.getResources().getString(R.string.install), true);
			break;

		case DownloadService.STATUS_PAUSED_BY_USER: {
			
			mDownloadLayout.setVisibility(View.VISIBLE);
			mVersion.setVisibility(View.GONE);
			mSize.setVisibility(View.GONE);
			
			
			setActionButton(mBlueTextColor, R.drawable.download_button_blue, getContext()
					.getResources().getString(R.string.go_on), true);
			long totalSize = mAppUpdateData.aum.getSize();
			long downloadedSize = getDownloadedFileSizeById(dlId);
			setDownloadProgressLayoutItem(getContext().getResources().getString(R.string.pause),
					getProgressString(totalSize, downloadedSize),
					getProgress(totalSize, downloadedSize));
		}
			break;

		case DownloadService.STATUS_PAUSED_BY_ERROR: {
			mDownloadLayout.setVisibility(View.VISIBLE);
			mVersion.setVisibility(View.GONE);
			mSize.setVisibility(View.GONE);
			
			long totalSize = mAppUpdateData.aum.getSize();
			long downloadedSize = getDownloadedFileSizeById(dlId);
			setDownloadProgressLayoutItem(getContext().getResources().getString(R.string.pause),
					getProgressString(totalSize, downloadedSize),
					getProgress(totalSize, downloadedSize));
			setActionButton(mOrangeTextColor, R.drawable.download_button_orange, getContext()
					.getResources().getString(R.string.retry), true);
		}
			break;
		case DownloadService.STATUS_PENDING: {
			mDownloadLayout.setVisibility(View.VISIBLE);
			mVersion.setVisibility(View.GONE);
			mSize.setVisibility(View.GONE);
			
			long totalSize = mAppUpdateData.aum.getSize();
			long downloadedSize = getDownloadedFileSizeById(dlId);
			setDownloadProgressLayoutItem(getContext().getResources().getString(R.string.waiting),
					getProgressString(totalSize, downloadedSize),
					getProgress(totalSize, downloadedSize));
			setActionButton(mGrayTextColor, R.drawable.download_button_gray, getContext()
					.getResources().getString(R.string.waiting), true);
		}
			break;
		case DownloadService.STATUS_DOWNLOADING: {
			mDownloadLayout.setVisibility(View.VISIBLE);
			mVersion.setVisibility(View.GONE);
			mSize.setVisibility(View.GONE);
			
			long totalSize = mAppUpdateData.aum.getSize();
			setDownloadProgressLayoutItem(getSpeedString(mDowloadSpeed),
					getProgressString(totalSize, mDownloadedSize),
					getProgress(totalSize, mDownloadedSize));

			setActionButton(mGrayTextColor, R.drawable.download_button_gray, getContext()
					.getResources().getString(R.string.pause), true);
		}
			break;
		case DownloadService.STATUS_PREPARE_TO_DOWNLOAD: {
			mDownloadLayout.setVisibility(View.VISIBLE);
			mVersion.setVisibility(View.GONE);
			mSize.setVisibility(View.GONE);
			
			long totalSize = mAppUpdateData.aum.getSize();
			long downloadedSize = getDownloadedFileSizeById(dlId);
			setDownloadProgressLayoutItem(
					getContext().getResources().getString(R.string.prepare_download),
					getProgressString(totalSize, downloadedSize), -1);
			setActionButton(mGrayTextColor, R.drawable.download_button_gray, getContext()
					.getResources().getString(R.string.pause), true);

		}
			break;
		case DownloadService.STATUS_PREPARE_TO_STOP: {
			mDownloadLayout.setVisibility(View.VISIBLE);
			mVersion.setVisibility(View.GONE);
			mSize.setVisibility(View.GONE);
			
			long totalSize = mAppUpdateData.aum.getSize();
			long downloadedSize = getDownloadedFileSizeById(dlId);
			setDownloadProgressLayoutItem("0K/S", getProgressString(totalSize, downloadedSize), -1);
			setActionButton(mGrayTextColor, R.drawable.download_button_gray, getContext()
					.getResources().getString(R.string.go_on), true);
		}
			break;
		case DownloadService.STATUS_DOWNLOAD_OUT_OF_DATE: // 下载过期状态，强制处理为有更新状态，点击后重新开始下载
		case DownloadService.STATUS_NEED_TO_UPDATE: {
			mDownloadLayout.setVisibility(View.GONE);
			mVersion.setVisibility(View.VISIBLE);
			mSize.setVisibility(View.VISIBLE);
			
			mVersion.setText(getVersionString());
			mSize.setText(getSizeString(false));
			
			setActionButton(mBlueTextColor, R.drawable.download_button_blue, getContext()
					.getResources().getString(R.string.update), true);
		}
			break;
		case DownloadService.STATUS_PAUSED_BY_MOBILE_NETWORK:
		case DownloadService.STATUS_NO_STATUS:
			Log.e(TAG, "wrong status happen:" + status);
			break;

		default:
			break;
		}
	}

	@Override
	public int getType() {
		return 1;
	}

	@Override
	public void onPackageInstalled(String pkgName) {
		if (pkgName.equals(mAppUpdateData.aum.getPackageName())) {
			if (mTipDialog != null && mTipDialog.isShowing()) {
				mTipDialog.dismiss();
			}

			if (mListener != null) {
				mListener.onNeedToReloadData(mAppUpdateData);
			}
		}
	}

	@Override
	public void onPackageUninstalled(String pkgName) {
		if (pkgName.equals(mAppUpdateData.aum.getPackageName())) {

			if (mTipDialog != null && mTipDialog.isShowing()) {
				mTipDialog.dismiss();
			}

			if (mListener != null) {
				mListener.onNeedToReloadData(mAppUpdateData);
			}
		}
	}

	@Override
	public void onDownloadCreated(DownloadItem di) {
	}

	@Override
	public void onDownloadRemoved(String id) {
	}

	@Override
	public void onDownloadChanged(DownloadItem di) {
	}

	@Override
	public void onProgressChanged(String id, long downloaded, long speed) {
		String dlId = DownloadUtils.generateDownloadId(mAppUpdateData.aum.getPackageName(),
				mAppUpdateData.aum.getVersionCode());
		if (!dlId.equals(id)) {
			return;
		}
		
		mDowloadSpeed = speed;
		mDownloadedSize = downloaded;

		//setupViewByStatus();
	}

}
